home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 287_01 / cline.c < prev    next >
Text File  |  1989-05-23  |  6KB  |  151 lines

  1. #include <stdio.h>
  2. #include <gds.h>
  3.  
  4. /*===========================================================*
  5.  *                                                           *
  6.  *  This file contain only 1 public routine:                 *
  7.  *                                                           *
  8.  *      Line(x1,y2,x2,y2)                                    *
  9.  *              draw a line from (x1,y1) to (x,y2)           *
  10.  *              inclusively                                  *
  11.  *                                                           *
  12.  *===========================================================*/
  13.  
  14. /* returns a 4 bit code giving information of a point relative */
  15. /* to the window. The 4 bits represent left, right, above      */
  16. /* and below of the window                                     */
  17. #define getcode(x,y) (x<WINX1 ?1:(x>WINX2 ?2:0))|(y<WINY1 ?4:(y>WINY2 ?8:0))
  18.  
  19. /*-----------------------------------------------------------*
  20.  *  The algorithm used in clipping and drawing a line        *
  21.  *  is adapted from the book "Fundamentals of interactive    *
  22.  *  Computer Graphics" by Foley[1982]                        *
  23.  *                                                           *
  24.  *  I would not try to explain the algorithm here. Interested*
  25.  *  user should refer the book                               *
  26.  *                                                           *
  27.  *-----------------------------------------------------------*/
  28.  
  29. Line(x1,y1,x2,y2)
  30. int x1,y1,x2,y2;
  31. {
  32.     int d,incr1,incr2,xdir,ydir,dir;
  33.     register int dx, dy;
  34.  
  35.     x1+=ORGX;  /* get absolute location */
  36.     y1+=ORGY; 
  37.     x2+=ORGX; 
  38.     y2+=ORGY;
  39.  
  40. /* clipping of the line, refer to Foley[1982] for explanation */
  41.     for (;;) {
  42.         if ((incr1=getcode(x1,y1)) & (incr2=getcode(x2,y2))) return;
  43.         if (!(incr1 | incr2)) break;
  44.         if (incr1)
  45.             clip(incr1,&x1,&y1,x2,y2);
  46.         else
  47.             clip(incr2,&x2,&y2,x1,y1);
  48.     }
  49.  
  50.     xdir=ydir=0;
  51.     if ((dx=x2-x1) < 0) { 
  52.         dx = -dx; 
  53.         xdir=1; 
  54.     }
  55.     if ((dy=y2-y1) < 0) { 
  56.         dy = -dy; 
  57.         ydir=1; 
  58.     }
  59.     if (dx == 0) {         /* a vertical line ? */
  60.         if (ydir) y1=y2;
  61.         vertl(x1,y1,++dy,1);
  62.         return;
  63.     }
  64.     if (dy == 0) {         /* a horizontal line ? */
  65.         if (xdir) x1=x2;
  66.         horzl(x1,y1,++dx);
  67.         return;
  68.     }
  69.     dir = (xdir == ydir) ? 1 : -1;
  70.     if (dy <= dx) {
  71.         if (xdir) {
  72.             x1=x2; 
  73.             y1=y2;
  74.         }
  75.         d = (incr1 = dy << 1) - dx;
  76.         incr2 = (dy - dx) << 1;
  77.          /* . . . . . . . . . . . . . . . . . . . . . . . .*/
  78.          /* When to use lline1 or lline2 is determined by  */
  79.          /* experiment result. The objective is to maximize*/
  80.          /* the speed in drawing line                      */
  81.          /* . . . . . . . . . . . . . . . . . . . . . . . .*/
  82.         if (dy > (dx >> 1)) 
  83.             /* . . . . . . . . . . . . . . . . . . . . . . . .*/
  84.             /* absolute value of the slope of the line is     */
  85.             /* greater than 1/2. Use lline1 to draw the line  */
  86.             /* . . . . . . . . . . . . . . . . . . . . . . . .*/
  87.             lline1(x1,y1,dir,dx,d,incr1,incr2);
  88.         else
  89.             /* . . . . . . . . . . . . . . . . . . . . . . . .*/
  90.             /* absolute value of the slope of the line        */
  91.             /* is between 0 and 1/2 (excluding 0). use lline2 */
  92.             /* to draw the line                               */
  93.             /* . . . . . . . . . . . . . . . . . . . . . . . .*/
  94.             lline2(x1,y1,dir,dx,d,incr1,incr2);
  95.     } 
  96.     else {
  97.         if (ydir) {
  98.             x1=x2; 
  99.             y1=y2;
  100.         }
  101.         d = (incr1 = dx << 1) - dy;
  102.         incr2 = (dx - dy) << 1;
  103.          /* . . . . . . . . . . . . . . . . . . . . . . . .*/
  104.          /* When to use lline3 or lline4 is determined by  */
  105.          /* experiment result. The objective is to maximize*/
  106.          /* the speed in drawing line                      */
  107.          /* . . . . . . . . . . . . . . . . . . . . . . . .*/
  108.         if (dx >= (dy >> 2))
  109.             /* . . . . . . . . . . . . . . . . . . . . . . . .*/
  110.             /* absolute value of the slope of the line is     */
  111.             /* greater than 4. Use lline3 to draw the line    */
  112.             /* . . . . . . . . . . . . . . . . . . . . . . . .*/
  113.             lline3(x1,y1,dir,dy,d,incr1,incr2);
  114.         else
  115.             /* . . . . . . . . . . . . . . . . . . . . . . . .*/
  116.             /* absolute value of the slope of the line        */
  117.             /* is between infinitive and 4. use lline4        */
  118.             /* to draw the line                               */
  119.             /* . . . . . . . . . . . . . . . . . . . . . . . .*/
  120.             lline4(x1,y1,dir,dy,d,incr1,incr2);
  121.     }
  122. }
  123.  
  124. /*-----------------------------------------------------------*
  125.  *  chop off the part of the line which is outside the window*
  126.  *-----------------------------------------------------------*/
  127. static clip(code,x1,y1,x2,y2)
  128. int code,*x1,*y1,x2,y2;
  129. {
  130.     register int dx,dy;
  131.     int temp;
  132.  
  133.     dx=x2 - *x1;
  134.     dy=y2 - *y1;
  135.  
  136.     if (code & 0x0c) {
  137.         if (dy) {
  138.             temp = code & 0x08 ? WINY2 : WINY1;
  139.             *x1 += (dx * (temp - *y1) + (dy >> 1)) / dy;
  140.         }
  141.         *y1 = temp;
  142.         return;
  143.     }
  144.     if (dx) {
  145.         temp = code & 0x02 ? WINX2 : WINX1;
  146.         *y1 += (dy * (temp - *x1) + (dx >> 1)) / dx;
  147.     }
  148.     *x1 = temp;
  149. }
  150.  
  151.